#ifndef XXQTDEFINE_H
#define XXQTDEFINE_H

#include <QString>
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QMessageBox>

#include <functional>

// 声明
#define XX_KEY(name) const static char * const name;
#define XX_KEY_C(cls,name,value) const char * const cls::name = value;
#define XX_KEY_(name,value) const char * const name = value;

// deprecated by 2021-11-22，使用 XX_OBJC_PROPERTY_BASE
#define XX_PROPERTY(type,name,get,set) \
    public: \
        Q_PROPERTY(type name READ get WRITE set USER true) \
        virtual type get() const { return name; } \
        virtual void set(type param) { name = param; } \
    private: \
        type name;
// deprecated by 2021-11-22，使用 XX_OBJC_PROPERTY_BASE_POLISH
#define XX_PROPERTY_POLISH(type,name,get,set) \
    public: \
        Q_PROPERTY(type name READ get WRITE set USER true) \
        virtual type get() const { return name; } \
        virtual void set(type param) {  \
            name = param;\
            polish();\
        } \
    protected: \
        type name;
// deprecated by 2021-11-22，使用 XX_OBJC_PROPERTY_BASE
#define XX_PROPERTY_SIMPLE(type,name) \
    public: \
        Q_PROPERTY(type name READ name##Get WRITE name##Set USER true) \
        type name##Get() const { return name; } \
        void name##Set(type param) { name = param; } \
    private: \
        type name;


#define XX_OBJC_PROPERTY_RW(_type_,_name_) \
    public: \
        Q_PROPERTY(_type_ _name_ READ get_##_name_ WRITE set_##_name_ USER true) \
        virtual _type_ get_##_name_() const { return _name_; } \
        virtual void set_##_name_(_type_ _param_) { _name_ = _param_; } \
    private: \
        _type_ _name_;

#define XX_OBJC_PROPERTY_RW_POLISH(_type_,_name_) \
    public: \
        Q_PROPERTY(_type_ _name_ READ get_##_name_ WRITE set_##_name_ USER true) \
        virtual _type_ get_##_name_() const { return _name_; } \
        virtual void set_##_name_(_type_ _param_) { _name_ = _param_; polish();} \
    private: \
        _type_ _name_;

/*
 * FileSystem
*/
/* 检查文件路径是否有效，目录无效并创建，文件无效可以选择是否创建 */
#define XX_SAFE_FILEPATH(path,createFile) \
    {\
        QFileInfo fileInfo(path);\
        if(!fileInfo.dir().exists()){\
            QDir().mkpath(fileInfo.absolutePath());\
        } \
        \
        if(!fileInfo.exists()&&createFile) {\
            QFile file(path);\
            file.open(QIODevice::ReadWrite);\
            file.close();\
        }\
    }
/* 检查目录路径是否有效， 目录无效并创建*/
#define XX_SAFE_DIRPATH(path) \
    {\
        QFileInfo fileInfo(path);\
        if(!fileInfo.dir().exists()){\
            QDir().mkpath(fileInfo.absoluteFilePath());\
        } \
    }
/*
 * QWindow的属性
*/
#define XX_MODAL_WINDOW(w) \
    { \
        w->setWindowModality(Qt::WindowModal);\
        w->setAttribute(Qt::WA_DeleteOnClose);\
        w->setWindowFlags(Qt::Window);\
    }

/*
 * MessageBox
*/
#define XX_MESSAGEBOX(message,type,btn) \
    {\
        QMessageBox mb(QCoreApplication::applicationName(),\
                       message,\
                       type,\
                       QMessageBox::Yes | QMessageBox::Default,\
                       QMessageBox::NoButton,\
                       QMessageBox::NoButton);\
        mb.button(QMessageBox::Yes)->setText(btn);\
        mb.exec();\
    }
#define XX_INFOBOX(message,btn) XX_MESSAGEBOX(message,QMessageBox::Information,btn)
#define XX_WARNBOX(message,btn) XX_MESSAGEBOX(message,QMessageBox::Warning,btn)

/*
 * Dispatch
*/
/**
 * must be
 * #include <mutex>
 * #include <funtional>
*/
#define XX_ONCE(block) \
{ \
    static std::once_flag once;\
    std::call_once(once,block);\
}


namespace XXqtDefine {
    /* FileSystem */
    void safeDirInFilePath(const QString &filePath);
    QDir safeDir(const QString &path);
    void copyDir(const QString &dirPath, const QString &newDirPath, std::function<void(QString from, QString to, bool succeed, QString msg)> block=nullptr);
    void copy(const QString &path, const QString &newPath);
    QString searchFile(const QString &dirPath, const QString &fileName);

	QString file_md5(const QString &path);
    QString getSystemDirPath();
    QString getAppDirPath();

    /* QWindow */
    void modelWindow(QWidget &widget);
    void widgetShadowEffect(QWidget *widget, int radius=12, QColor color=QColor(0,0,0,127));

    /* QMessageBox */
    void messageBox(const QString &title, const QString &message, QMessageBox::Icon type, const QString &button);
    void messageBox(const QString &title, const QString &message, QMessageBox::Icon type, const QStringList &buttons, std::function<void(QString button)> block);
    void messageBoxInfo(const QString &title, const QString &message, const QString &button);
    void messageBoxQuestion(const QString &title, const QString &message, const QStringList &buttons, std::function<void(QString button)> block);
    void messageBoxCritical(const QString &title, const QString &message, const QString &button);
	
	QString getRandomString(int length);
    QString getRawUUID();

    /* QColor */
    QColor colorFromHexString(const QString &hex);
    QString colorToHexString(const QColor &color);

    /* Json */
    QString variantToJsonString(const QVariant &var, bool indented);
    bool variantToJsonFile(const QVariant &var, const QString &path, bool indented);
    QVariant variantFromJsonString(const QString &json);
    QVariant variantFromJsonBytes(const QByteArray &json);
    QVariant variantFromJsonFile(const QString &path);

    /* QSS */
    bool qssLoad(QApplication *app, const QString &path);
    bool qssLoad(QWidget *widget, const QString &path);
    QByteArray qssRead(const QString &path);
}

#endif // XXQTDEFINE_H
